package com.zeny.xdclass.controller;

import com.zeny.xdclass.common.ResponseResult;
import com.zeny.xdclass.config.WeChatConfig;
import com.zeny.xdclass.domain.User;
import com.zeny.xdclass.domain.VideoOrder;
import com.zeny.xdclass.mapper.VideoOrderMapper;
import com.zeny.xdclass.service.UserService;
import com.zeny.xdclass.service.VideoOrderService;
import com.zeny.xdclass.utils.JwtUtils;
import com.zeny.xdclass.utils.WXPayUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Map;
import java.util.SortedMap;

/**
 * @ClassName WechatController
 * @Description TODO
 * @Author zeny
 */
@Controller
@Api(tags = "微信模块")
public class WechatController {

    @Autowired
    private WeChatConfig weChatConfig;

    @Autowired
    private UserService userService;

    @Autowired
    private VideoOrderService videoOrderService;


    /**
     * @Description
     *  获取用户当前访问的页面，返回登录授权连接qrcodUrl地址，该地址包涵了登录授权地址、回调地址、当前访问页面等信息
     *  当用户同意授权后，跳转到回调地址并携带微信端的code和当前访问页面
     * @param access_page
     * @return com.zeny.xdclass.common.ResponseResult
     **/
    @ApiOperation(value = "微信扫一扫登录URL")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "access_page", required = true)
    })
    @GetMapping("/api/v1/wechat/login_url")
    @ResponseBody
    public ResponseResult loginUrl(@RequestParam(value = "access_page", required = true) String access_page) throws UnsupportedEncodingException {

        //获取开发平台重定向地址
        String redirectUurl = weChatConfig.getWxopenRedirectUurl();
        //进行编码
        String callbackUrl = URLEncoder.encode(redirectUurl, "GBK");
        String qrcodUrl = String.format(weChatConfig.getOpenQrcodeUrl(), weChatConfig.getWxopenAppid(), callbackUrl, access_page);
        return ResponseResult.ok().data(qrcodUrl);
    }

    /**
     * @Description
        用户扫码成功并同意登录后，跳转到该回调地址，并携带上code以及用户当前访问的页面
     * @param code
     * @param state
     * @param response
     * @return void
     **/
    @GetMapping("/api/ucenter/wx/callback")
    @ApiOperation(value = "微信回调URL(携带code)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code", required = true)
    })
    public void wechatUserCallback(@RequestParam(value = "code", required = true) String code,
                                   String state, HttpServletResponse response) throws IOException {

        User user = userService.saveWeChatUser(code);
        if (user != null) {
            //生成jwt
            String token = JwtUtils.genJsonWebToken(user);
            response.sendRedirect(state + "?token=" + token + "&head_img=" + user.getHeadImg() + "&name=" + URLEncoder.encode(user.getName(),"UTF-8"));
        }
    }

    /**
     * @Description
     * 微信支付回调地址 是支付成功后，微信端调用的地址，那么，该地址需要是公网地址
     * 方案一: 到阿里云等购买域名绑定ip;
     * 方案二: 使用ngrok等内网穿透工具，如http://zeny.free.idcfengye.com/api/order/weixinPay/weixinNotify中的
     * http://zeny.free.idcfengye.com 是ngrok分配的域名，映射到本地的服务端口
     * 调用链路: 微信端 -> ngrok -> http://zeny.free.idcfengye.com -> http://localhost:port ->
     * http://localhost:port/api/order/weixinPay/weixinNotify
     * 实现微信端调用本地接口;
     * @param request
     * @param response
     * @return void
     **/
    @PostMapping("/api/order/weixinPay/weixinNotify")
    @ApiOperation(value = "微信支付回调")
    public void orderCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
        InputStream inputStream = request.getInputStream();
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = in.readLine()) != null) {
            sb.append(line);
        }
        in.close();
        inputStream.close();
        Map<String, String> callbackMap = WXPayUtil.xmlToMap(sb.toString());
        System.out.println(callbackMap);
        SortedMap<String, String> sortedMap = WXPayUtil.getSortedMap(callbackMap);
        //判断签名是否正确
        if (WXPayUtil.isCorrectSign(sortedMap, weChatConfig.getKey())) {
            //更新订单状态
            if ("SUCCESS".equals(sortedMap.get("result_code"))) {
                String outTradeNo = sortedMap.get("out_trade_no");
                VideoOrder dbVideoOrder = videoOrderService.findByOutTradeNo(outTradeNo);
                if (dbVideoOrder.getState() == 0) {
                    //未支付状态 -> 已支付
                    VideoOrder videoOrder = new VideoOrder();
                    videoOrder.setOpenid(sortedMap.get("openid"));
                    videoOrder.setOutTradeNo(outTradeNo);
                    videoOrder.setNotifyTime(new Date());
                    videoOrder.setState(1);
                    int row = videoOrderService.updateVideoOderByOutTradeNo(videoOrder);
                    if (row == 1) {
                        //通知微信订单处理成功
                        response.setContentType("text/xml");
                        response.getWriter().println("success");
                    }
                }
            }
        }
        response.setContentType("text/xml");
        response.getWriter().println("success");
    }
}
